import Node from './node'
const copyData = (data, tree) => {
  const newData = {}
  for (const key in data) {
    if (data.hasOwnProperty(key) && key !== tree.prop.children) {
      newData[key] = data[key]
    }
  }
  return newData
}
const copyNode = (node, tree) => {
  const newData = copyData(node.data, tree)
  if (node.isLeaf) {
    return newData
  }
  newData[tree.prop.children] = []
  node.indeterminateChildNodes.forEach(item => {
    newData[tree.prop.children].push(copyNode(item, tree))
  })
  return newData
}

export default class Tree {
  constructor(options) {
    this.accordion = true
    for (const name in options) {
      if (options.hasOwnProperty(name)) {
        this[name] = options[name]
      }
    }
    if (typeof this.prop !== 'object') {
      this.prop = {
        label: 'label',
        key: 'key',
        leaf: 'leaf',
        disabled: 'disabled',
        children: 'children'
      }
    }
    if (this.lazy && !this.load) {
      throw new Error('loadNodeFunction is required!')
    }
    this.nodesMap = new Map()
    this.root = new Node({
      data: this.data,
      tree: this
    })
  }
  getCheckNode() {
    const arr = []
    this.nodesMap.forEach(item => {
      if (item.checked) {
        arr.push(item.data)
      }
    })
    return arr
  }
  setCheckNode(keys, bor = true) {
    const nodesMap = this.nodesMap

    if (Array.isArray(keys)) {
      keys.forEach(item => {
        const node = nodesMap.get(item)
        if (node) node.check = bor
      })
    } else {
      const node = nodesMap.get(keys)
      if (node) nodesMap.get(keys).check = bor
    }
  }
  getCheckNodeTree() {
    const root = this.root

    if (Array.isArray(root.data)) {
      const newTree = []
      root.indeterminateChildNodes.forEach(item => {
        newTree.push(copyNode(item, this))
      })
      return newTree
    } else {
      return copyNode(root, this)
    }
  }
  clearCheckNode() {
    this.nodesMap.forEach(item => {
      item.check = false
    })
  }
  clearExpandNode() {
    this.nodesMap.forEach(item => {
      item.isExpanded = false
    })
  }
  appendNodes(key, nodes) {
    const parent = this.nodesMap.get(key)
    if (!parent) {
      return
    }
    if (Array.isArray(nodes)) {
      if (typeof nodes === 'object') {
        nodes.forEach(item => {
          parent.appendChild(item)
        })
      }
    } else if (typeof nodes === 'object') {
      parent.appendChild(nodes)
    }
  }
  delectNodeByKey(keys) {
    if (Array.isArray(keys)) {
      keys.forEach(item => {
        const node = this.nodesMap.get(item)
        if (node) node.remove()
      })
    } else {
      const node = this.nodesMap.get(keys)
      node.remove()
    }
  }
}
